#ifndef COMMON_DIRECTORYITERATOR_H_
#define COMMON_DIRECTORYITERATOR_H_
#include <fermat/common/file.h>
#include <fermat/common/path.h>
#include <dirent.h>
#include <string>
namespace fermat {


/*!
* The DirectoryIterator class is used to enumerate
* all files in a directory.
*
* DirectoryIterator has some limitations:
*   * only forward iteration (++) is supported
*   * an iterator copied from another one will always
*     point to the same file as the original iterator,
*     even is the original iterator has been advanced
*     (all copies of an iterator share their state with
*     the original iterator)
*   * because of this you should only use the prefix 
*     increment operator
*/
class  DirectoryIterator {
public:
	/*!
	*Creates the end iterator.
	*/
	DirectoryIterator();

	/*!
	* Creates a directory iterator for the given path.
	*/	
	DirectoryIterator(const std::string& path);
		
	/*!
	* Creates a directory iterator for the given path.
	*/	
	DirectoryIterator(const DirectoryIterator& iterator);

	/*!
	* Creates a directory iterator for the given file.
	*/		
	DirectoryIterator(const File& file);

	/*!
	* Creates a directory iterator for the given path.
	*/
	DirectoryIterator(const Path& path);
		
	/*!
	* Destroys the DirectoryIterator.
	*/
	~DirectoryIterator();
		
	/*!
	* @return the current filename.
	*/
	const std::string& name() const;
		
	/*!
	* @return the current path.
	*/	
	const Path& path() const;

	int error();

	DirectoryIterator& operator = (const DirectoryIterator& it);
	DirectoryIterator& operator = (const File& file);
	DirectoryIterator& operator = (const Path& path);
	DirectoryIterator& operator = (const std::string& path);
	
	/*!
	* prefix
	*/
	 DirectoryIterator& operator ++ ();   


	/*!
	* postfix
	*/
	DirectoryIterator operator ++ (int); 

	
	const File& operator * () const;
	File& operator * ();
	const File* operator -> () const;
	File* operator -> ();
	
	bool operator == (const DirectoryIterator& iterator) const;
	bool operator != (const DirectoryIterator& iterator) const;

protected:
	DIR*        _pDir;
	int         _dc;
	int         _rc;
	Path        _path;
	File        _file;
	std::string	_current;
protected:
	void clear();
	std::string next();	
	int init(const std::string &path); 
};


//
// inlines
//
inline const std::string& DirectoryIterator::name() const
{
	return _path.getFileName();
}

inline int DirectoryIterator::error()
{
	return _rc;
}
inline const Path& DirectoryIterator::path() const
{
	return _path;
}


inline const File& DirectoryIterator::operator * () const
{
	return _file;
}


inline File& DirectoryIterator::operator * ()
{
	return _file;
}


inline const File* DirectoryIterator::operator -> () const
{
	return &_file;
}


inline File* DirectoryIterator::operator -> ()
{
	return &_file;
}


inline bool DirectoryIterator::operator == (const DirectoryIterator& iterator) const
{
	return name() == iterator.name();
}


inline bool DirectoryIterator::operator != (const DirectoryIterator& iterator) const
{
	return name() != iterator.name();
}

} 


#endif 